/* a simple pager program with vim-like keymap
 * help manual:
 * q: quit program
 * j: scroll one line down
 * k: scroll one line up
 * d: scroll half screen down
 * u: scroll half screen up
 * g: goto first line
 * G: goto last line
 */
#include <curses.h>
#include <stdlib.h>

static FILE *fp;
static int mrow, mcol; // size of standard screen

static void
usage(char *cmd)
{
  printf("usage: %s filename\n", cmd);
  exit(1);
}

static void
init()
{
  initscr();
  raw();    // raw mode
  noecho(); // switch to non-echo
  keypad(stdscr, TRUE); // enable function key(F1,Up/Down...)
  getmaxyx(stdscr, mrow, mcol); // get size of standard screen
  curs_set(0); // turn cursor off
}

int main(int argc, char *argv[])
{
  if (argc != 2) {
    usage(argv[0]);
  }
  if ((fp = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "%s: can't open file %s\n", argv[0], argv[1]);
    exit(2);
  }
  int c;
  int lcnt = 0;
  while ((c = fgetc(fp)) != EOF) {
    if (c == '\n') { // it only fit to unix format text file(not DOS)
      lcnt++;
    }
  }

  // initialization
  init();
  WINDOW *pad = newpad(lcnt, mcol);

  rewind(fp);
  while ((c = fgetc(fp)) != EOF) {
    pechochar(pad, c);
  }
  fclose(fp);

  int padrow = 0;
  prefresh(pad, padrow, 0, 0, 0, mrow - 1, mcol - 1);

  while ((c = wgetch(pad)) != 'q') {
    switch (c) {
      case 'j':
        if (padrow < lcnt - mrow) {
          padrow++;
        }
        break;
      case 'k':
        if (padrow > 0) {
          padrow--;
        }
        break;
      case 'd':
        if (padrow + mrow/2 <= lcnt - mrow) {
          padrow += mrow/2;
        }else {
          padrow = lcnt - mrow;
        }
        break;
      case 'u':
        if (padrow >= mrow/2) {
          padrow -= mrow/2;
        }else {
          padrow = 0;
        }
        break;
      case 'g':
        padrow = 0;
        break;
      case 'G':
        padrow = lcnt - mrow;
        break;
      default:
        break;
    }
    prefresh(pad, padrow, 0, 0, 0, mrow - 1, mcol - 1);
  }

  // clean up
  delwin(pad);
  endwin();
  exit(0);
}
